<script setup lang="ts">
import RoomStatus from './components/RoomStatus.vue'
import RoomMessage from './components/RoomMessage.vue'
import RoomAction from './components/RoomAction.vue'
import { io, Socket } from 'socket.io-client'
import { baseURL } from '@/utils/request'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
import { onMounted } from 'vue'
import { onUnmounted } from 'vue'
import type { Message, TimeMessages } from '@/types/room'
import { ref } from 'vue'
import { MsgType, OrderType } from '@/enums'
import type { ConsultOrderItem } from '@/types/consult'
import { getConsultOrderDetail } from '@/services/consult'
import { nextTick } from 'vue'
import { showToast } from 'vant'
defineOptions({
  name: 'Room'
})

const userStore = useUserStore()
const route = useRoute()
const list = ref<Message[]>([])
let socket: Socket
onMounted(() => {
  socket = io(baseURL, {
    // reconnectionDelayMax: 10000,
    auth: {
      // 这里的token后端说了 要用Bearer ${token}
      token: `Bearer ${userStore.user?.token} `
    },
    query: {
      orderId: route.query.orderId
    }
  })
  socket.on('connect', () => {
    console.log('connect')
    list.value = []
  })
  socket.on('disconnect', () => {
    console.log('disconnect')
  })
  socket.on('connect_error', () => {
    console.log('connect_error')
  })
  // chatMsgList 接收聊天记录
  socket.on('chatMsgList', ({ data }: { data: TimeMessages[] }) => {
    console.log(data)
    // 假设默认消息 [{createTime: '9:00', items: [1,2,3]}, {createTime: '10:00', items: [4,5,6]}, ...]
    // arr => [9: 00, 1, 2, 3, 10:00 , 4, 5, 6]
    const arr: Message[] = []
    data.forEach((item, index) => {
      // 最早时间如何处理 消息列表数组 索引为0的createTime 记录lastTime
      if (index === 0) lastTime.value = item.createTime
      // createTime 消息
      arr.push({
        createTime: item.createTime,
        id: item.createTime,
        msg: {
          content: item.createTime
        },
        msgType: MsgType.Notify
      })
      // items消息
      arr.push(...item.items)
    })
    list.value.unshift(...arr)
    loading.value = false
    // 没数据 给用户提示没有消息数据了
    if (data.length === 0) {
      return showToast('没有历史数据了')
    }
    // nextTick这段逻辑，如果不加判断 不管是首次默认消息，还是下拉刷新都会滚动到最下面
    // 加个开关，第一次触发逻辑，触发好逻辑 在把开关 关了
    if (initMsg.value) {
      // initMsg初始值是true 可以进这个if
      nextTick(() => {
        window.scrollTo(0, document.body.scrollHeight)
        initMsg.value = false
      })
    }
  })
  // statusChange 接收订单状态改变
  socket.on('statusChange', () => {
    console.log('状态变化了')
    loadConsult()
  })
  // receiveChatMsg 接收消息
  socket.on('receiveChatMsg', async (val) => {
    // val就是消息Message类型
    // console.log(val)
    // list数据 就是消息列表，将后端给的消息对象，push进去就可以之后做渲染了
    list.value.push(val)
    // 控制滚动条滚到最下面
    // dom的更新是异步的 -> nextTick
    // function nextTick(callback?: () => void): Promise<void>
    // this.$nextTick() error vue3没有this
    // 第一种写法 await nextTick()
    // await nextTick()
    // 第二种写法 nextTick(cb) cb是回调函数
    nextTick(() => {
      window.scrollTo(0, document.body.scrollHeight)
    })
  })
})
onUnmounted(() => {
  socket.close()
})

// updateMsgStatus 消息已读

/**
 * 订单状态步骤
 * 1. 封装接口 -> 获取订单详情 状态
 *      onMounted
 * 2. 监听订单状态改变的事件 ->获取订单详情 拿到状态
 *      socket.on(statusChange, )
 * 3. 渲染的工作
 *    3.1 状态栏组件渲染
 *    3.2 操作栏 咨询中才能发送文字和图片 控制禁用逻辑
 */
const consult = ref<ConsultOrderItem>()
const loadConsult = async () => {
  const { data } = await getConsultOrderDetail(route.query.orderId as string)
  consult.value = data
}
onMounted(() => {
  loadConsult()
})
const handleSendText = (val: string) => {
  // console.log('儿子给我的', val)
  // emit发送消息
  // sendChatMsg 发送消息
  socket.emit('sendChatMsg', {
    // from 我们自己发消息 自己的id userStore里有自己的id
    from: userStore.user?.id,
    // to 给医生 医生的id
    to: consult.value?.docInfo?.id,
    // 消息类型，注意对象的键根据接口文档 msgType 第一个字母是小写
    msgType: MsgType.MsgText,
    // 消息 对象，里面字段content - 文字信息 picture - 图片
    // 本次业务是文字聊天，所以使用content 值就是儿子传过来的消息
    msg: {
      content: val
    }
  })
}

/**
 * 下拉刷新步骤分析
 * 1. PullRefresh组件使用
 * 2. 历史记录获取 emit getChatMsgList 获取聊天记录
 *      通过最早的时间获取 看文档
 *      最早时间如何处理 消息列表数组 第一项的createTime
 * 3. on 接收历史数据(之前已完成部分逻辑)
 *      加载中关闭
 * 4. 下拉后没数据 做提示没有数据了
 * 5. 首次加载消息 滚动到最下面
 *    下拉刷新（查看历史消息）不需要滚动到最下面
 * 6. 断网后重新连接，数据重新新增 数据重复问题
 *    在connect的事件，清空数据即可
 */
const initMsg = ref(true) // 初始值开关，用于首次滚动到最下面
const loading = ref(false)
const lastTime = ref('')
const onRefresh = () => {
  // setTimeout(() => {
  //   showToast('刷新成功')
  //   loading.value = false
  // }, 1000)
  //向socket服务端发送数据 参数：pageSize: number, lastTime: string, orderId: string
  socket.emit('getChatMsgList', 20, lastTime.value, consult.value?.id)
}
</script>

<template>
  <div class="room-page">
    <cp-nav-bar title="医生问诊室" />
    <room-status :status="consult?.status" :countdown="consult?.countdown" />
    <van-pull-refresh v-model="loading" @refresh="onRefresh">
      <room-message :list="list"></room-message>
    </van-pull-refresh>
    <!-- 咨询中可以聊天发文字 - 不是咨询中就禁用 -->
    <room-action
      :disabled="consult?.status !== OrderType.ConsultChat"
      @send-text="handleSendText"
    ></room-action>
  </div>
</template>

<style lang="scss" scoped>
.room-page {
  padding-top: 90px;
  padding-bottom: 60px;
  min-height: 100vh;
  box-sizing: border-box;
  background-color: var(--cp-bg);
  .van-pull-refresh {
    width: 100%;
    min-height: calc(100vh - 150px);
  }
}
</style>
